<template>
  <div class="enhanced-table-container">
    <div class="table-controls">
      <el-switch
        v-model="showIndexLocal"
        style="margin-bottom: 10px"
        inline-prompt
        active-text="序号"
        inactive-text="序号"
      />
    </div>
    <el-table
      ref="tableRef"
      v-loading="loading"
      :data="visibleData"
      :row-key="rowKey"
      :span-method="mergeMethod"
      height="800"
      @selection-change="handleSelectionChange"
      v-bind="$attrs"
    >
      <!-- 序号列 -->
      <el-table-column
        v-if="showIndexLocal"
        type="index"
        label="序号"
        width="60"
        :index="(index: number) => props.data[index][props.indexKey] || index + 1"
      />

      <!-- 多选列 -->
      <el-table-column
        v-if="selectionType === 'multiple'"
        type="selection"
        :selectable="checkSelectable"
      />

      <!-- 单选列 -->
      <el-table-column
        v-if="selectionType === 'single'"
      >
        <template #default="scope">
          <el-radio
            v-model="selectedRow"
            :label="scope.row[rowKey]"
            @change="handleSingleSelect(scope.row)"
          >&nbsp;</el-radio>
        </template>
      </el-table-column>

      <!-- 动态列渲染 -->
      <template v-for="column in columns" :key="column.prop">
        <el-table-column
          v-bind="column"
          :fixed="column.fixed"
        >
          <template #default="scope">
            <template v-if="column.children">
              <el-table-column
                v-for="subColumn in column.children"
                :key="subColumn.prop"
                v-bind="subColumn"
              >
                <template #default="scope">
                  <slot
                    :name="subColumn.prop"
                    v-bind="scope"
                  >
                    {{ scope.row[subColumn.prop] }}
                  </slot>
                </template>
              </el-table-column>
            </template>
            <template v-else>
              <slot
                :name="column.prop"
                v-bind="scope"
              >
                {{ scope.row[column.prop] }}
              </slot>
            </template>
          </template>
        </el-table-column>
      </template>
    </el-table>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import type { TableColumnCtx } from 'element-plus'
import Sortable from 'sortablejs'
import type { SortableEvent } from 'sortablejs'

export interface TableColumn {
  label: string
  prop: string
  fixed?: boolean | 'left' | 'right'
  width?: number | string
  children?: TableColumn[]
  validator?: (value: any) => boolean
}

interface Props {
  data: any[]
  columns: TableColumn[]
  rowKey: string
  selectionType?: 'single' | 'multiple' | 'none'
  mergeColumns?: string[]
  pageSize?: number
  indexKey?: string // 用于序号列的字段名
  showIndex?: boolean // 控制序号列显示隐藏
}

const props = withDefaults(defineProps<Props>(), {
  selectionType: 'none',
  mergeColumns: () => [],
  pageSize: 50,
  indexKey: 'id',
  showIndex: true
})

const emit = defineEmits<{
  (e: 'selection-change', selection: any[]): void
  (e: 'row-drag', payload: { oldIndex: number; newIndex: number }): void
  (e: 'update:show-index', value: boolean): void
}>()

// 表格引用
const tableRef = ref()
const loading = ref(false)
const currentPage = ref(1)
const selectedRow = ref('')
const selectedRows = ref<any[]>([])

// 序号列显示控制
const showIndexLocal = ref(props.showIndex)

// 监听外部showIndex变化
watch(() => props.showIndex, (newVal) => {
  showIndexLocal.value = newVal
})

// 监听本地showIndex变化
watch(showIndexLocal, (newVal) => {
  emit('update:show-index', newVal)
})

// 可见数据计算
const visibleData = computed(() => {
  const start = (currentPage.value - 1) * props.pageSize
  const end = start + props.pageSize
  return props.data.slice(start, end)
})

// 序号计算
const calculateIndex = (index: number) => {
  return (currentPage.value - 1) * props.pageSize + index + 1
}

// 单选处理
const handleSingleSelect = (row: any) => {
  selectedRows.value = [row]
  emit('selection-change', [row])
}

// 多选处理
const handleSelectionChange = (selection: any[]) => {
  selectedRows.value = selection
  emit('selection-change', selection)
}

// 检查是否可选
const checkSelectable = (row: any) => {
  return true // 可以根据需求添加条件
}

// 合并单元格方法
const mergeMethod = ({ row, column, rowIndex, columnIndex }: any) => {
  if (props.mergeColumns.includes(column.property)) {
    // 找到当前值的第一次出现位置
    let firstIndex = rowIndex;
    // 向上查找相同值的第一次出现位置
    while (firstIndex > 0 && props.data[firstIndex - 1][column.property] === row[column.property]) {
      firstIndex--;
    }
    
    let rowspan = 0;
    let colspan = 1;
    
    if (firstIndex === rowIndex) {
      // 计算需要合并的行数
      for (let i = firstIndex; i < props.data.length; i++) {
        if (props.data[i][column.property] === row[column.property]) {
          rowspan++;
        } else {
          break;
        }
      }
      return { rowspan, colspan };
    } else {
      return { rowspan: 0, colspan: 1 };
    }
  }
}

// 行拖拽功能
onMounted(() => {
  const tbody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
  Sortable.create(tbody, {
    onEnd(evt: SortableEvent) {
      if (typeof evt.oldIndex === 'number' && typeof evt.newIndex === 'number') {
        emit('row-drag', { 
          oldIndex: evt.oldIndex, 
          newIndex: evt.newIndex 
        })
      }
    }
  })
})

// 数据验证
const validateData = (data: any[]) => {
  const errors: string[] = []
  
  data.forEach((row, index) => {
    props.columns.forEach(column => {
      if (column.validator && !column.validator(row[column.prop])) {
        errors.push(`第${index + 1}行的${column.label}数据格式不正确`)
      }
    })
  })
  
  return errors
}

// 虚拟滚动处理
const handleScroll = async (e: Event) => {
  const target = e.target as HTMLElement
  const { scrollTop, clientHeight, scrollHeight } = target
  
  if (scrollHeight - scrollTop - clientHeight < 100) {
    loading.value = true
    currentPage.value++
    await nextTick()
    loading.value = false
  }
}

// 导出方法供父组件使用
defineExpose({
  validateData,
  tableRef,
  selectedRows
})
</script>

<style scoped>
.enhanced-table-container {
  width: 100%;
}

.table-controls {
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  gap: 10px;
}

:deep(.el-table__row) {
  cursor: move;
}

:deep(.el-radio) {
  margin-right: 0;
}
</style> 